package com.hdu.metrics_center.metrics.service;

import com.hdu.metrics_center.enums.RedisCommandType;
import com.hdu.metrics_center.mapper.MetricsMetaMapper;
import com.hdu.metrics_center.metrics.MetricsExecuteReq;
import com.hdu.metrics_center.metrics.MetricsExecuteResult;
import com.hdu.metrics_center.metrics.MetricsValue;
import com.hdu.metrics_center.metrics.meta.MetricsMetaDO;
import com.hdu.metrics_center.redisCommand.RedisCommandFactory;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.hdu.metrics_center.utils.RedisCommandBuildUtils.buildMetricsExecuteReq;


@Service
public class MetricsService {

    private final RedisCommandFactory redisCommandFactory;
    private final MetricsMetaMapper metricsMetaMapper;

    public MetricsService(RedisCommandFactory redisCommandFactory, MetricsMetaMapper metricsMetaMapper) {
        this.redisCommandFactory = redisCommandFactory;
        this.metricsMetaMapper = metricsMetaMapper;
    }


    public MetricsExecuteResult delMetrics(String metricsName, Map<String, Object> params) {
        return saveOrUpdateOrDelete(metricsName, null, params, OP.DELETE);
    }

    public MetricsExecuteResult saveMetrics(String metricsName, Object value, Map<String, Object> params) {
        return saveOrUpdateOrDelete(metricsName, value, params, OP.SAVE);
    }

    public MetricsExecuteResult queryMetrics(String metricsName, Map<String, Object> params) {
        return saveOrUpdateOrDelete(metricsName, null, params, OP.QUERY);
    }

    public List<MetricsExecuteResult> queryMetricsList(List<String> metricsNames, Map<String, Object> params) {
        return metricsNames
                .stream()
                .map(metricsName -> queryMetrics(metricsName, params))
                .collect(Collectors.toList());
    }


    private MetricsExecuteResult saveOrUpdateOrDelete(String metricsName,
                                                      Object value,
                                                      Map<String, Object> params,
                                                      OP op) {
        MetricsMetaDO metricsMeta = metricsMetaMapper.queryMetricsMetaByMetricsName(metricsName);
        String keyTemplate;
        String fieldTemplate;
        RedisCommandType redisCommandType;
        switch (op) {
            case QUERY:
                keyTemplate = metricsMeta.getMetricsQueryMeta().getKeyTemplate();
                fieldTemplate = metricsMeta.getMetricsQueryMeta().getFieldTemplate();
                redisCommandType = metricsMeta.getMetricsQueryMeta().getQueryCommand();
                break;
            case DELETE:
                keyTemplate = metricsMeta.getMetricsSaveAndDelMeta().getKeyTemplate();
                fieldTemplate = metricsMeta.getMetricsSaveAndDelMeta().getFieldTemplate();
                redisCommandType = metricsMeta.getMetricsSaveAndDelMeta().getDelCommand();
                break;
            case SAVE:
                keyTemplate = metricsMeta.getMetricsSaveAndDelMeta().getKeyTemplate();
                fieldTemplate = metricsMeta.getMetricsSaveAndDelMeta().getFieldTemplate();
                redisCommandType = metricsMeta.getMetricsSaveAndDelMeta().getSaveCommand();
                break;
            default:
                throw new RuntimeException("op error");
        }
        MetricsExecuteReq metricsExecuteReq = buildMetricsExecuteReq(
                keyTemplate,
                fieldTemplate,
                params
        );
        metricsExecuteReq.setRedisCommandType(redisCommandType);

        MetricsValue metricsValue = new MetricsValue();
        metricsValue.setTimestamp(System.currentTimeMillis());
        metricsValue.setValue(value);
        metricsExecuteReq.setValue(metricsValue);

        return redisCommandFactory.getRedisCommand(redisCommandType).operate(metricsExecuteReq);
    }


    public enum OP {
        QUERY, DELETE, SAVE
    }

}
